var _gl = require('opengl');
var _createMesh = require('glcore/meshbuffer.js').createMesh;
var _inherit = require('core/inherit.js');
var _geometry = require('core/glm.js');
var _v2 = _geometry.vec2f;

var _Text = require('drawable/text.js');
var _Color = require('utils/color.js');

function Style() {
    this.mOutline_type = 0;
    this.mOutline_thickness = 0;
    this.mColor = new Float32Array([0, 0, 0, 1]);
    this.mOffset = new _v2();
}
Style.prototype.load = function (font, text) {
    font.outline_type(this.mOutline_type);
    font.outline_thickness(this.mOutline_thickness);
    font.load(text);
};
Style.prototype.outline_type = function (type) {
    this.mOutline_type = type;
    return this;
};
Style.prototype.outline_thickness = function (t) {
    this.mOutline_thickness = t;
    return this;
};
Style.prototype.color = function (c) {
    if (arguments.length == 0) {
        return this.mColor;
    }

    if (typeof c == 'string') {
        _Color.parseColor(c, this.mColor);
    } else {
        this.mColor.set(c);
    }
    return this;
};
Style.prototype.offset = function () {
    if (arguments.length == 0) {
        return this.mOffset;
    }

    this.mOffset.set.apply(this.mOffset, arguments);
    return this;
};

/**
 * @param b mesh buffer
 * @param element mesh point element
 * @param point p2t2 point
 * @param twidths text widths
 * @param glyphs
 * @param len text length
 * @param style style index
 * @param offset glyphs offset
 * @param color
 * @returns {number}
 */
function setup(b, element, point, twidths, glyphs, len, style, offset, color) {
    var x = offset[0];
    var y = offset[1];

    var gindex = 0;
    var windex = 0;
    var order = [0, 1, 2, 5];
    var pindex = len * 6 * style;

    for (var i = 0; i < len; i++) {
        x += twidths[windex + 1];

        for (var rect = 0; rect < 4; rect++) {
            glyphs.get(point, rect * 4 + gindex);
            point[0] += x;
            point[1] += y;
            element.set(point);
            element.set(color, 4);
            b.push(pindex + order[rect]);
        }
        b.copy(pindex + 2, pindex + 3, 1);
        b.copy(pindex + 1, pindex + 4, 1);

        x += twidths[windex];
        gindex += 16;
        windex += 2;
        pindex += 6;
    }
    return x - offset[0];
}

function StyleText(material, font, styles) {
    _Text.call(this, material, font);
    this.mStyles = styles || [];// if styles given
}
_inherit(StyleText, _Text);
StyleText.prototype.addStyle = function () {
    var style = new Style();
    this.mStyles.push(style);
    return style;
};
StyleText.prototype.createMesh = function () {
    var styles = this.mStyles.length;
    if (styles == 0) {
        this.mVisiable = false;
        return;
    }

    var text = this.mText;
    var len = this.mText.length;
    var b = this.mBuffer = _createMesh('p2t2c4', len * 6 * styles, _gl.TRIANGLES);
    var element = new Float32Array(b.adapter().buffer());
    var height = this.font.height;

    var twidths = new Float32Array(len * 2);// [advance,kerning]
    var glyphs = new Float32Array(len * 16);// [{x1,y1,s0,t0},{x1,y2,s0,t1},{x2,y1,s1,t0},{x2,y2,s1,t1}]
    var point = new Float32Array(4);
    var offset = new _v2();

    var witdh = 0;
    for (var s = 0; s < styles; s++) {
        var style = this.mStyles[s];

        style.load(this.font, text);

        this.font.measure(text, twidths);
        this.font.glyphs_rect(text, glyphs);
        offset.set(0, -this.font.ascender);
        offset.add(style.offset());

        witdh = setup(b, element, point, twidths, glyphs, len, s, offset, style.color());
    }

    this.setSize(witdh, height);
    this.setCenter(0, height);
    b.upload();
};

StyleText.Style = Style;

module.exports = StyleText;
